package com.rizzo.analytics.domain.trigger;


import com.rizzo.analytics.domain.PersistentEntity;
import com.rizzo.analytics.domain.account.Account;
import com.rizzo.infrastructure.web.validator.Save;
import com.rizzo.infrastructure.web.validator.Update;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.codehaus.jackson.annotate.JsonIgnore;
import org.codehaus.jackson.annotate.JsonIgnoreProperties;
import org.joda.time.DateTime;
import org.springframework.util.StringUtils;

import javax.persistence.*;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Null;
import javax.validation.constraints.Size;
import javax.validation.groups.Default;
import java.io.Serializable;
import java.util.Date;

@Entity
@Table(name = "triggers")
@JsonIgnoreProperties({"account", "version", "created"})
public class Trigger implements Serializable, PersistentEntity {

    public static final int INSTANCE_NAME_MAX_LENGTH = 30;
    public static final int INSTANCE_INDEX_MAX_LENGTH = 6;
    public static final int SERVICE_MAX_LENGTH = 300;
    public static final int TRESHOLD_TYPE = 9;
    public static final int TRESHOLD_PRECISION = 10;
    public static final int TRESHOLD_SCALE = 2;

    @Id
    @Null(groups = Save.class, message = "trigger.id.field.save.present")
    @GeneratedValue
    private Long id;

    @Version
    @JsonIgnore
    private Long version;

    @Size(min = 1, max = Trigger.INSTANCE_NAME_MAX_LENGTH, message = "trigger.instancename.field.max.length",
            groups = {Default.class, Save.class, Update.class})
    @Column(nullable = true, length = Trigger.INSTANCE_NAME_MAX_LENGTH, name = "instance_name")
    private String instanceName;

    @Size(min = 1, max = Trigger.INSTANCE_INDEX_MAX_LENGTH, message = "trigger.instanceindex.field.max.length",
            groups = {Default.class, Save.class, Update.class})
    @Column(nullable = true, length = Trigger.INSTANCE_INDEX_MAX_LENGTH, name = "instance_index")
    private String instanceIndex;

    @NotNull(groups = {Default.class, Save.class}, message = "trigger.service.field.required")
    @Size(min = 1, max = Trigger.SERVICE_MAX_LENGTH, message = "trigger.service.field.max.length",
            groups = {Default.class, Save.class, Update.class})
    @Column(nullable = false, length = Trigger.SERVICE_MAX_LENGTH)
    private String service;

    @NotNull(groups = {Default.class, Save.class}, message = "trigger.tresholdtype.field.required")
    @Enumerated(EnumType.STRING)
    // TODO add Pattern
    @Column(nullable = false, length = Trigger.TRESHOLD_TYPE, name = "treshold_type")
    private TresholdType tresholdType;

    @NotNull(groups = {Default.class, Save.class}, message = "trigger.treshold.field.required")
    @Column(nullable = false, precision = Trigger.TRESHOLD_PRECISION, scale = Trigger.TRESHOLD_SCALE)
    private Double treshold;

    @JsonIgnore
    @Column(nullable = false)
    private Date created;

    @JsonIgnore
    @ManyToOne(cascade = CascadeType.PERSIST, fetch = FetchType.EAGER)
    private Account account;

    public Trigger() {
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public Long getVersion() {
        return version;
    }

    public void setVersion(Long version) {
        this.version = version;
    }

    public String getInstanceName() {
        return instanceName;
    }

    public void setInstanceName(String instanceName) {
        this.instanceName = instanceName;
    }

    public String getInstanceIndex() {
        return instanceIndex;
    }

    public void setInstanceIndex(String instanceIndex) {
        this.instanceIndex = instanceIndex;
    }

    public String getService() {
        return service;
    }

    public void setService(String service) {
        this.service = service;
    }

    public TresholdType getTresholdType() {
        return tresholdType;
    }

    public void setTresholdType(TresholdType tresholdType) {
        this.tresholdType = tresholdType;
    }

    public Double getTreshold() {
        return treshold;
    }

    public void setTreshold(Double treshold) {
        this.treshold = treshold;
    }

    public Date getCreated() {
        return created;
    }

    public void setCreated(Date created) {
        this.created = created;
    }

    public Account getAccount() {
        return account;
    }

    public void setAccount(Account account) {
        this.account = account;
    }

    public void mergeBeforeUpdate(Trigger trigger) {
        this.instanceName = StringUtils.hasText(trigger.getInstanceName()) ? trigger.getInstanceName() : this.instanceName;
        this.instanceIndex = StringUtils.hasText(trigger.getInstanceIndex()) ? trigger.getInstanceIndex() : this.instanceIndex;
        this.service = StringUtils.hasText(trigger.getService()) ? trigger.getService() : this.service;
        this.tresholdType = (trigger.getTresholdType() != null) ? trigger.getTresholdType() : this.tresholdType;
        this.treshold = (trigger.getTreshold() != null) ? trigger.getTreshold() : this.treshold;
        this.created = (trigger.getCreated() != null) ? this.getCreated() : this.created;
    }

    public void prepareBeforeSave() {
        this.created = new DateTime().toDate();
    }

    @Override
    public boolean equals(Object o) {
        return EqualsBuilder.reflectionEquals(this, o, new String[]{"account"});
    }

    @Override
    public int hashCode() {
        return HashCodeBuilder.reflectionHashCode(this, new String[]{"account"});
    }
}
